from urllib.parse import quote_plus

from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import QueuePool

from utils.log_utils import get_logger

# 获取一个命名的日志记录器
logger = get_logger(__name__)


class MySQLPool:
    POOL_SIZE = 5
    MAX_OVERFLOW = 10
    POOL_TIMEOUT = 30
    POOL_RECYCLE = 600

    def __init__(self,config:dict):
        self.host = config['host']
        self.port = config['port']
        self.username = config['username']
        self._password = config['password']
        self.database = config['database']
        self.log = config['mysql_log']
        logger.info(
            f'host {self.host},port {self.port},username {self.username},database {self.database},log {self.log}')

        try:
            # 在构建连接字符串时才对密码进行编码
            password_encoded = quote_plus(self._password)
            db_url = f'mysql+pymysql://{self.username}:{password_encoded}@{self.host}:{self.port}/{self.database}?charset=utf8mb4'

            self.engine = create_engine(
                db_url,
                echo=self.log,
                pool_size=self.POOL_SIZE,
                max_overflow=self.MAX_OVERFLOW,
                pool_pre_ping=True,
                pool_timeout=self.POOL_TIMEOUT,
                poolclass=QueuePool,
                pool_recycle=self.POOL_RECYCLE
            )
            self.session_factory = sessionmaker(bind=self.engine)
        except Exception as e:
            raise RuntimeError(f"Failed to initialize database engine: {e}") from e

    def get_session(self):
        return self.session_factory()

    def test(self):
        try:
            with self.engine.connect() as conn:
                result = conn.execute(text("SELECT 'hello world'"))
                print(result.all())
        except Exception as e:
            logger.info(f"Test query failed: {e}")

    def close(self):
        """主动关闭连接池资源"""
        if hasattr(self, 'engine'):
            logger.info('close engine')
            self.engine.dispose()
        if hasattr(self, 'db_pool'):
            logger.info('close db pool')
            self.db_pool.close()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()
